In computing systems, including general purpose and embedded implementations, resource and memory management are very important to proper system operation. Memory management typically occurs at several levels, such as, for example, hardware memory management, OS (Operating System) memory management, and application memory management. OS and application memory management rely on various software techniques for the allocation and de-allocation of memory utilized by the system. In the OS, memory is allocated to user programs, and reused by other programs when it is no longer required. Application memory management typically involves supplying the memory required for program objects and data structures from the limited resources available, and recycling that memory for reuse when it is no longer required.
One common form of memory allocation error is memory leak, which can be a major resource issue leading to system malfunctions and negative performance impacts. In general, a memory leak occurs when allocated memory is not freed after use, or when a needed reference to that allocated memory (e.g., a pointer to the memory allocation) is deleted thereby rendering the memory no longer reachable or “live” to the system. Memory leaks can take many forms (e.g. occurring in contiguous block or fragmentally), and can occur in a variety of different memory systems such as flattened memory architectures or those with virtual memory spaces. Reckless use of dynamic memory allocation can lead to memory management problems, which cause performance degradation, unpredictable execution or crashes.
RAID (Redundant Array of Independent Disks) controllers, an example of an embedded computing technology, typically need to support RTOS (Real Time Operating Systems), which are capable of multi-tasking as well as supporting dynamic memory allocations. Due to system complexity and performance requirements, both processor memory and cache memory need to be supported by one or more RAID controllers. Obviously, system memory management is critical among the many tasks that require dynamic memory allocation during program execution. RAID controller firmware, most probably written in C and C++, uses “malloc” and “new”, respectively, for dynamic memory allocation from a “heap”; and additionally utilizes “free” and “delete” commands, which permit the memory to return to the heap after its use. Note that the term “heap” is also referred to as “memory pool”.
For programs that are perfectly designed and implemented, except for memory pieces that are allocated at the start-of-the-day and need to be globally accessible afterwards (e.g., singletons), memory allocation should be balanced during normal operations to ensure that the computing system does not run out of resources.
For firmware programs running on RAID controllers, multiple tasks can be spawned to provide services at different contexts. Most of the time, however, the coordination and information exchange among the tasks results in a decoupling of memory allocation, which render potential memory leak detection and isolation operations more difficult. Information gathered by one task may be needed by another task from a different module via a so-called “pass by reference” (or pointer) mechanism. In this case, the memory blocks allocated can unlikely be freed by the same task. Passing host 10 requests to a destination driver using internal one or more buffer structures (to hold SCSI operations) are good examples of such situations.
The severity of this issue increases with the number of tasks and the complexity of the individual tasks. For a typical RAID controller, up to 60 tasks with different priorities may run simultaneously from a firmware image compiled from millions of lines of code. As a matter of fact, memory leak due to unbalanced memory allocation is a major problem faced by almost all large computer programs.
FIG. 1 illustrates a schematic diagram of a prior art information exchange system 100 including the depiction of decoupled memory allocation and free activities performed by different tasks. The prior art system 100 includes an event monitor 110 that monitors the scope of messages from other programs or user actions such as mouse clicks or key presses. A task scheduler 125 schedules Task T1 120, Task T2 130 and Task T3 135. Upon a request of a particular event, memory can be allocated from a heap 105 as shown at block 115. The task scheduler 125 then passes the Task T1 120 to Task T3 135 via a dBlock (not shown). The dBlock (not shown) can be processed and memory can be returned to the heap 105 as indicated respectively at blocks 140 and 145.
FIG. 2 illustrates the internal structure of a prior art allocated memory piece or mempiece 200. The mempiece 200 includes an actual memory allocated 215 and two memory headers such as “vxWorksMemBlk” 205 and “LSI_ESG_MEM_HOOK” 210.
The structure of mempiece 200 can be provided as indicated below:
struct memPiece{  struct vxWorksMemBlk  {   struct vxWorksMemBlk * next;   unsigned int size : 31;   unsigned int free : 1;  };  struct LSI_ESG_MEM_HOOK  {   unsigned long signature;   unsigned long length;   unsigned long taskld;   void *   vxwblock;  };  byte * memBody;}
A structure is used to group variables together under one name. The mempiece structure depicted in FIG. 2 generally includes two structures “vxWorksMemBlk” and “LSI_ESG_MEM_HOOK”. The structure “vxWorksMemBlk” includes a “vxWorksMemBlk” pointer for maintaining the address of a next adjacent block of memory allocated in memory pool. The structure “LSI_ESG_MEM_HOOK” includes the use of an unsigned signature variable to indicate the state (free or allocated) of memory and an unsigned long variable to determine which task allocates this chunk memory.
The common practice for isolating memory leak issue has involved either introducing an external utility program that “spies” or monitors programs or creating spy task(s) within an application that records that memory allocation/free process. In addition to the cost and development time incurred with both options, performance degradation due to extra overhead introduced by these spy utilities/tasks has been another major concern, especially for performance critical RAID controllers systems.
A need therefore exists for implementing a straight-forward and efficient memory leak detection and isolation mechanism, without introducing additional internal tasks or external utility programs, while minimizing system performance degradation. Cost efficiency should also be achieved.